<?php

namespace common\components;

use common\models\User;
use Yii;
use yii\base\ActionEvent;
use yii\base\Behavior;
use yii\helpers\Url;
use yii\web\Controller;

/**
 * 微信网页授权行为
 *
 * 该行为必须依赖weixin组件
 *
 * 在控制器中加入behaviors方法
 * ~~~
 * public function behaviors()
 * {
 *     return [
 *         'weixinAuthorize' => [
 *             'class' => \common\components\WeixinAuthorizeFilter::className(),
 *             'autoLogin' => false, //如果有自动登录需求 设置为true
 *         ],
 *     ];
 * }
 * ~~~
 *
 * 获取的微信用户的openid 将存储在session里面
 * ~~~
 * $openid = Yii::$app->getSession()->get('weixin_openid')
 * ~~~
 *
 * @package common\components
 */
class WeixinAuthorizeFilter extends Behavior
{
    /** @var bool 是否自动登录 */
    public $autoLogin = false;

    public function events()
    {
        return [Controller::EVENT_BEFORE_ACTION => 'beforeAction'];
    }

    /**
     * @param ActionEvent $event
     * @return bool
     */
    public function beforeAction($event)
    {
        /** @var Controller $controller */
        $controller = $this->owner;

        if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'com.tencent.mm') {
            /** @var Weixin $weixin */
            $weixin = Yii::$app->weixin;
            $session = Yii::$app->getSession();
            if ($session->get('weixin_authorize', false)) {
                if ($this->autoLogin && !$session->get('weixin_logged', false)) {
                    $this->login($session->get('weixin_openid'));
                }
                return true;
            }
            Yii::info('微信授权');
            if (Yii::$app->getUser()->isGuest && empty($_GET['code'])) {
                $params = $_GET;
                unset($params['r']);
                $controller->redirect(
                    $weixin->getAuthorizeUrl(Url::to([$controller->route, $params], true), 'snsapi_base')
                );
            } elseif (!empty($_GET['code'])) {
                $result = $weixin->getAuthorizeAccessToken($_GET['code']);
                $session->set('weixin_authorize', true);
                if (isset($result['openid'])) {
                    $session->set('weixin_openid', $result['openid']);
                    if ($this->autoLogin) {
                        $this->login($result['openid']);
                    }
                }
            }
        }
        return true;
    }

    /**
     * 登录
     *
     * @param string $openid 用户openid
     */
    protected function login($openid)
    {
        if (!$openid) {
            return;
        }

        Yii::info('微信登录');
        $user = Yii::$app->getUser();
        Yii::$app->getSession()->set('weixin_logged', true);

        $userIdentity = User::findByWeixinOpenid($openid);
        if ($userIdentity) {
            $user->login($userIdentity);
        }
    }
}
